#include "StdAfx.h"
#include "SyncFileServer.h"

using namespace boost::filesystem;
static void ProcessPacketSystem( net::INetPacket* pPacket );
static void ProcessPacketClient( net::INetPacket* pPacket, const Json::Value& Config );

static bool bWork = true;
void CallServer( const Json::Value& ServerConfig )
{
	net::IMessageQueue* pMessageQueue = NULL;
	xgc_uint16 port = ServerConfig.get( "Port", 17361 ).asUInt();
	xgc_long_ptr hServer = net::StartServer( "0.0.0.0", port, &pMessageQueue, 1000, 5000, net::ProtocalDefault, 10 );

	while( bWork )
	{
		net::INetPacket* pPacketSys = pMessageQueue->SysMessage();
		if( pPacketSys )
		{
			ProcessPacketSystem( pPacketSys );
			pPacketSys->release();
		}

		net::INetPacket* pPacketCil = pMessageQueue->PopMessage();
		if( pPacketCil )
		{
			ProcessPacketClient( pPacketCil, ServerConfig );
			pPacketCil->release();
		}

		if( pPacketCil == xgc_nullptr && pPacketSys == xgc_nullptr )
		{
			Sleep(1);
		}
	}
}

void ProcessPacketSystem( net::INetPacket* pPacket )
{
	const net::MessageHeader* header = reinterpret_cast< const net::MessageHeader* >( pPacket->header() );
	xgc_byte_cptr data = pPacket->data();
	xgc_uint32 size = pPacket->size();

	switch( header->type )
	{
	case EVENT_ACCEPT:
		{
			net::network_t handle = pPacket->handle();
			net::Param_SetUserdata Param;
			Param.handle = handle;
			Param.userdata_ptr = (xgc_lpvoid) new CClient( handle );

			net::ExecuteState( Operator_SetUserdata, (xgc_long_ptr)&Param );
		}
		break;
	case EVENT_ERROR:
	case EVENT_CLOSE:
		{
			CClient* pClient = reinterpret_cast< CClient* >( pPacket->userdata() );
			net::network_t handle = pPacket->handle();
			net::Param_SetUserdata Param;
			Param.handle = handle;
			Param.userdata_ptr = xgc_nullptr;
			net::CloseLink( pPacket->handle() );

			SAFE_DELETE( pClient );
		}
		break;
	case EVENT_CONNECT:
		{
			net::network_t handle = pPacket->handle();
			net::Param_SetUserdata Param;
			Param.handle = handle;
			Param.userdata_ptr = (xgc_lpvoid) new CClient( handle );

			net::ExecuteState( Operator_SetUserdata, (xgc_long_ptr)&Param );
		}
		break;
	case EVENT_PING:
		break;
	case EVENT_PONG:
		break;
	}
}

void ProcessPacketClient( net::INetPacket* pPacket, const Json::Value& Config )
{
	const net::MessageHeader* header = reinterpret_cast< const net::MessageHeader* >( pPacket->header() );
	xgc_byte_cptr data = pPacket->data();
	xgc_uint32 size = pPacket->size();
	
	switch( header->type )
	{
	case C2S_SYNC_SESSION:
		{
			CClient* pClient = reinterpret_cast< CClient* >( pPacket->userdata() );
			if( pClient )
			{
				ASSERT_RETURN( size == sizeof(C2S_SyncSession), void(0) );
				const C2S_SyncSession* pMsg = reinterpret_cast< const C2S_SyncSession* >( data );
				pClient->ProcessSyncSession( Config, *pMsg );
			}
		}
		break;
	case C2S_SYNC_DIRECTORY:
		{
			CClient* pClient = reinterpret_cast< CClient* >( pPacket->userdata() );
			if( pClient )
			{
				ASSERT_RETURN( size == sizeof(C2S_SyncDirectory), void(0) );
				const C2S_SyncDirectory* pMsg = reinterpret_cast< const C2S_SyncDirectory* >( data );
				pClient->ProcessSyncDirectory( Config, *pMsg );
			}
		}
		break;
	case C2S_SYNC_FILE_STATE:
		{
			CClient* pClient = reinterpret_cast< CClient* >( pPacket->userdata() );
			if( pClient )
			{
				ASSERT_RETURN( size == sizeof(C2S_SyncFileState), void(0) );
				const C2S_SyncFileState* pMsg = reinterpret_cast< const C2S_SyncFileState* >( data );
				pClient->ProcessSyncFileState( Config, *pMsg );
			}
		}
		break;
	case C2S_SYNC_FILE:
		{
			CClient* pClient = reinterpret_cast< CClient* >( pPacket->userdata() );
			if( pClient )
			{
				ASSERT_RETURN( size >= sizeof(C2S_SyncFile), void(0) );
				const C2S_SyncFile* pMsg = reinterpret_cast< const C2S_SyncFile* >( data );
				pClient->ProcessSyncFile( Config, *pMsg );
			}
		}
		break;
	}
}

//////////////////////////////////////////////////////////////////////////
CClient::CClient( net::network_t hNetwork ) 
: mNetwork( hNetwork )
, mCurrentNode( NULL )
{

}

CClient::~CClient()
{

}

void CClient::SearchDirectory( Json::Value& currentDirectory, boost::filesystem::path path )
{
	for( boost::filesystem::directory_iterator iter( currentDirectory ); iter != boost::filesystem::directory_iterator(); ++iter )
	{
		if( boost::filesystem::is_directory( *iter ) )
		{
			SearchDirectory( currentDirectory[iter->path().filename().generic_string()], iter->path() );
		}
		else
		{
			currentDirectory.append( iter->path().filename().generic_string() );
		}
	}
}

void CClient::ProcessSyncSession( const Json::Value& Config, const C2S_SyncSession& Msg )
{
	const Json::Value& JSession = Config[Msg.session];
	if( JSession.isString() )
	{
		boost::filesystem::path root( JSession.asString(), boost::filesystem::native );
		SearchDirectory( JRoot, root );
		net::SendPacket( mNetwork, (xgc_byte_cptr)&Msg, sizeof(Msg) );
	}
}

void CClient::ProcessSyncDirectory( const Json::Value& Config, const C2S_SyncDirectory& Msg )
{

}

void CClient::ProcessSyncFileState( const Json::Value& Config, const C2S_SyncFileState& Msg )
{
}

void CClient::ProcessSyncFile( const Json::Value& Config, const C2S_SyncFile& Msg )
{

}
